#ifdef WX_PRECOMP
#include "wx_pch.h"
#else
#include <wx/wx.h>
#endif //WX_PRECOMP

#include "component_parser.h"
#include "cell_data_item.h"
#include "exchanger.h"

namespace
{
  class ExchangerForType : public BaseParser::BaseExchanger
  {
  public:
    virtual ~ExchangerForType() {}

    virtual ExchangerForType* Clone() const
    {
      return new ExchangerForType(*this);
    }

    virtual bool Read(const wxString& source, void* destination) const
    {
      long result = 0;
      if (!source.ToLong(&result))
      {
        result = 0;
      }

      ComponentType ct = TYPE_UNKNOW;
      switch (result)
      {
        case 1: case 2: case 3: case 4: case 5: case 6: case 8: case 10:
          ct = static_cast<ComponentType>(result);
          break;
        default:
          ct = TYPE_UNKNOW;
      }
      *static_cast<ComponentType*>(destination) = ct;
      return true;
    }

    virtual bool Write(const wxString& itemName, void* source, wxXmlNode* destination) const
    {
      return true;
    }
  };

} // end of anonumous namespace

// Parce one item from XML document
bool ComponentParser::OnParceComplete()
{
  if (Item.Type == TYPE_CHASSIS)
  {
    Item.RequredCellPosition = CELL_CHASSIS;
  }

  Result.push_back(Item);
  Item.Clear();
  return true;
}

const ComponentItemVectorType& ComponentParser::GetResult() const
{
  return Result;
}

ComponentParser::ComponentParser()
{
  SetHandler(wxT("id"), &Item.ID, Exchanger::ForInteger());
  SetHandler(wxT("name"), &Item.Name, Exchanger::ForString());
  SetHandler(wxT("image"), &Item.ImageName, Exchanger::ForString());
  SetHandler(wxT("type"), &Item.Type, ExchangerForType());
  SetHandler(wxT("class"), &Item.ChassisClass, Exchanger::ForInteger());

  SetHandler(wxT("req_tehn_level"), &Item.RequredTehnLevel, Exchanger::ForInteger());
  SetHandler(wxT("req_building"), &Item.RequredBuilding, Exchanger::ForString());

  SetHandler(wxT("cost_main"), &Item.CostMain, Exchanger::ForDouble());
  SetHandler(wxT("cost_second"), &Item.CostSecond, Exchanger::ForDouble());
  SetHandler(wxT("cost_money"), &Item.CostMoney, Exchanger::ForDouble());
  SetHandler(wxT("cost_pepl"), &Item.CostPeople, Exchanger::ForDouble());
  SetHandler(wxT("build_speed"), &Item.BuildSpeed, Exchanger::ForDouble());
  SetHandler(wxT("support_main"), &Item.SupportMain, Exchanger::ForDouble());
  SetHandler(wxT("support_second"), &Item.SupportSecond, Exchanger::ForDouble());
  SetHandler(wxT("exp_pricegrow"), &Item.ExpensePriceGrow, Exchanger::ForDouble());
  SetHandler(wxT("military"), &Item.IsMilitary, Exchanger::ForBool());

  SetHandler(wxT("hit_points"), &Item.HitPoints, Exchanger::ForDouble());
  SetHandler(wxT("laser_dr"), &Item.LaserDefence, Exchanger::ForDouble());
  SetHandler(wxT("bomb_dr"), &Item.RocketDefence, Exchanger::ForDouble());

  SetHandler(wxT("laser_damage"), &Item.LaserDamage, Exchanger::ForDouble());
  SetHandler(wxT("laser_ar"), &Item.LaserAttack, Exchanger::ForDouble());
  SetHandler(wxT("laser_number"), &Item.LaserNumber, Exchanger::ForInteger());
  SetHandler(wxT("bomb_damage"), &Item.RocketDamage, Exchanger::ForDouble());
  SetHandler(wxT("bomb_ar"), &Item.RocketAttack, Exchanger::ForDouble());
  SetHandler(wxT("bomb_number"), &Item.RocketNumber, Exchanger::ForInteger());

  SetHandler(wxT("weight"), &Item.Weight, Exchanger::ForDouble());
  SetHandler(wxT("max_weight"), &Item.MaxWeight, Exchanger::ForDouble());

  SetHandler(wxT("motivator"), &Item.Motivator, Exchanger::ForDouble());
  SetHandler(wxT("fuel"), &Item.Fuel, Exchanger::ForDouble());

  SetHandler(wxT("front_cells"), &Item.CellsFront, Exchanger::ForInteger());
  SetHandler(wxT("side_cells"), &Item.CellsSide, Exchanger::ForInteger());
  SetHandler(wxT("stern_cells"), &Item.CellsStern, Exchanger::ForInteger());
  SetHandler(wxT("transport_cells"), &Item.CellsTransport, Exchanger::ForInteger());
  SetHandler(wxT("external_cells"), &Item.CellsExternal, Exchanger::ForInteger());
  SetHandler(wxT("special_cells"), &Item.CellsSpecial, Exchanger::ForInteger());

  SetHandler(wxT("transport_capacity"), &Item.TransportCapacity, Exchanger::ForInteger());
  SetHandler(wxT("carrier"), &Item.CarrierCapacity, Exchanger::ForInteger());

  SetHandler(wxT("s1"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_FRONT));
  SetHandler(wxT("s3"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_SIDE));
  SetHandler(wxT("s4"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_STERN));
  SetHandler(wxT("s5"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_TRANSPORT));
  SetHandler(wxT("s2"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_EXTERNAL));
  SetHandler(wxT("s6"), &Item.RequredCellPosition, Exchanger::ForBinaryFlag(CELL_SPECIAL));

  SetHandler(wxT("bonus_hits"), &Item.BonusHitPoints, Exchanger::ForDouble());
  SetHandler(wxT("bonus_ldef"), &Item.BonusLaserDefence, Exchanger::ForDouble());
  SetHandler(wxT("bonus_rdef"), &Item.BonusRocketDefence, Exchanger::ForDouble());
  SetHandler(wxT("bonus_ldmg"), &Item.BonusLaserDamage, Exchanger::ForDouble());
  SetHandler(wxT("bonus_rdmg"), &Item.BonusRocketDamage, Exchanger::ForDouble());
  SetHandler(wxT("bonus_lar"), &Item.BonusLaserAttack, Exchanger::ForDouble());
  SetHandler(wxT("bonus_rar"), &Item.BonusRocketAttack, Exchanger::ForDouble());
  SetHandler(wxT("bonus_spd"), &Item.BonusSpeed, Exchanger::ForDouble());
  SetHandler(wxT("bonus_dst"), &Item.BonusDistance, Exchanger::ForDouble());
  SetHandler(wxT("bonus_invis"), &Item.BonusInvisible, Exchanger::ForDouble());
  SetHandler(wxT("bonus_det"), &Item.BonusDetect, Exchanger::ForDouble());
  SetHandler(wxT("bonus_supp"), &Item.BonusSupport, Exchanger::ForDouble());

  SetHandler(wxT("scan_strength"), &Item.ScanStrength, Exchanger::ForDouble());
  SetHandler(wxT("detect_range"), &Item.DetectRange, Exchanger::ForDouble());
  SetHandler(wxT("stealth_lvl"), &Item.StealthLevel, Exchanger::ForDouble());

  SetHandler(wxT("spec_ability"), &Item.SpecialAbility, Exchanger::ForString());
}

void ComponentParser::Clear()
{
  Item.Clear();
  Result.clear();
}
